<template>
  <CommonPage show-footer :show-header="false">
    <CrudTable
      ref="$table"
      v-model:query-items="queryItems"
      :extra-params="extraParams"
      :columns="columns"
      :get-data="api.getRoleList"
    >
      <template #queryBar>
        <QueryBarItem label="角色名称" :label-width="70">
          <n-input
            type="text"
            clearable
            placeholder="请输入角色名称"
            @keydown.enter="$table?.handleSearch"
            v-model:value="queryItems.searchKey"
          />
        </QueryBarItem>
        <QueryBarItem label="角色类型" :label-width="70">
          <n-select
            clearable
            filterable
            placeholder="请选择角色类型"
            :options="getOptions('ROLE_CATEGORY')"
            @keydown.enter="$table?.handleSearch"
            v-model:value="queryItems.category"
          />
        </QueryBarItem>
      </template>

      <template #title-right>
        <n-button
          type="primary"
          size="small"
          @click="
            () => {
              defaultCheckedKeys = []
              defaultExpandedKeys = []
              handleAdd()
            }
          "
        >
          <TheIcon icon="material-symbols:add" :size="18" class="mr-5" />
          新增角色
        </n-button>
      </template>
    </CrudTable>

    <!-- 新增/编辑/查看 -->
    <CrudModal
      style="width: 580px"
      :title="modalTitle"
      :loading="modalLoading"
      :show-footer="modalAction !== 'view'"
      @on-save="handleSave"
      v-model:visible="modalVisible"
    >
      <n-form
        ref="modalFormRef"
        label-placement="left"
        label-width="100"
        :model="modalForm"
        :disabled="modalAction === 'view'"
      >
        <n-form-item
          label="角色名称"
          path="name"
          :rule="{
            required: true,
            message: '请输入角色名称',
          }"
        >
          <n-input
            clearable
            placeholder="请输入角色名称"
            v-model:value="modalForm.name"
          />
        </n-form-item>
        <n-form-item
          label="角色类型"
          path="category"
          :rule="{
            required: true,
            message: '请选择角色类型',
          }"
        >
          <n-select
            clearable
            filterable
            placeholder="请选择角色类型"
            :options="getOptions('ROLE_CATEGORY')"
            v-model:value="modalForm.category"
          />
        </n-form-item>
        <n-form-item
          label="菜单权限"
          path="grantInfoList"
          :rule="{
            required: true,
            message: '请选择菜单权限',
          }"
        >
          <n-tree
            block-line
            expand-on-click
            checkable
            cascade
            key-field="id"
            label-field="title"
            :defaultCheckedKeys="defaultCheckedKeys"
            :defaultExpandedKeys="defaultExpandedKeys"
            :data="tree"
            @update:checked-keys="onTreeChange"
          />
        </n-form-item>
      </n-form>
    </CrudModal>
  </CommonPage>
</template>

<script setup>
import { h, onMounted } from 'vue'
import { NButton, NText } from 'naive-ui'
import { renderIcon, getOptions } from '@/utils'
import { useCRUD } from '@/composables'
import api from './api'

const $table = ref(null)
const router = useRouter()
const queryItems = ref({
  category: null,
})
const extraParams = ref({})

const columns = [
  {
    title: '序号',
    key: 'tableIndex',
    width: 100,
  },
  {
    title: '角色名称',
    key: 'name',
    width: 220,
  },
  {
    title: '角色类型',
    width: 220,
    render(row) {
      return h(
        NText,
        {},
        {
          default: () =>
            getOptions('ROLE_CATEGORY').find((v) => v.value === row.category)
              ?.label,
        }
      )
    },
  },
  {
    title: '创建时间',
    key: 'createTime',
  },
  {
    title: '操作',
    key: 'actions',
    width: 200,
    fixed: 'right',
    render(row) {
      return [
        h(
          NButton,
          {
            type: 'primary',
            size: 'small',
            secondary: true,
            style: 'margin-right: 10px;',
            onClick: async () => {
              const params = {
                id: row.id,
              }

              const { code, data } = await api.getRoleTree(params)

              if (code === 200) {
                const ids = data.grantInfoList.map((v) => v.menuId)
                defaultCheckedKeys.value = ids
                defaultExpandedKeys.value = ids

                handleEdit({
                  id: row.id,
                  name: row.name,
                  category: row.category,
                  grantInfoList: data.grantInfoList,
                })
              }
            },
          },
          {
            default: () => '编辑',
            icon: renderIcon('material-symbols:edit-outline', { size: 14 }),
          }
        ),

        h(
          NButton,
          {
            type: 'error',
            size: 'small',
            secondary: true,
            onClick: () => handleDelete([{ id: row.id }]),
          },
          {
            default: () => '删除',
            icon: renderIcon('material-symbols:delete-outline', { size: 14 }),
          }
        ),
      ]
    },
  },
]

const {
  modalVisible,
  modalAction,
  modalTitle,
  modalLoading,
  handleAdd,
  handleDelete,
  handleEdit,
  handleView,
  handleSave,
  modalForm,
  modalFormRef,
} = useCRUD({
  name: '角色',
  initForm: {},
  doCreate: api.updateRole,
  doDelete: api.delRole,
  doUpdate: api.updateRole,
  refresh: () => $table.value?.handleSearch(),
})

const tree = ref([])
const defaultCheckedKeys = ref([])
const defaultExpandedKeys = ref([])

onMounted(() => {
  getTree()
  $table.value?.handleQuery()
})

async function getTree() {
  const params = {
    visible: 'TRUE',
  }

  const { code, data } = await api.getTree(params)

  if (code === 200) {
    tree.value = data
  }
}

function onTreeChange(ids = []) {
  modalForm.value.grantInfoList = ids.map((v) => {
    return {
      menuId: v,
      buttonInfo: [],
    }
  })
}
</script>

<style lang="scss" scoped>
:deep(.n-card) {
  border: none !important;
}

:deep(.n-card__content) {
  padding: 0 !important;
  background-color: #f5f6fb !important;
}
</style>
